#include <common.h>
#include <scrn.h>



#define VGA_MAXY 25
#define VGA_MAXX 800


typedef struct
{
  u16int* textmemptr;
  u32int attrib;
  s32int csr_x;
  s32int csr_y;
}screen_t;

static screen_t s_scrn;

void move_csr(u16int x, u16int y)
{
   u16int temp;

   temp = y* 80 + x;

   outportb(0x3D4, 14);
   outportb(0x3D5, temp >> 8);
   outportb(0x3D4, 15);
   outportb(0x3D5, temp);

   s_scrn.csr_x = x;
   s_scrn.csr_y = y;
}

void scroll()
{
   u16int blank, tmp;
  
   blank = ' '|s_scrn.attrib<<8;

   if(s_scrn.csr_y >= VGA_MAXY)
   {
      tmp = s_scrn.csr_y - VGA_MAXY + 1;
      memcpyw(s_scrn.textmemptr,s_scrn.textmemptr + tmp*80,
              (25 - tmp)*80*2);

      memsetw(s_scrn.textmemptr + (25 -tmp)*80, blank, 80);
      s_scrn.csr_y = 25 -1;
   }
}
void cls()
{
    u16int blank;

    blank = ' ' | s_scrn.attrib << 8;

    memsetw(s_scrn.textmemptr,blank,80*25);

    move_csr(0,0);

}
void putch(s8int c)
{
    u16int* where;
    s32int x = s_scrn.csr_x;
    s32int y = s_scrn.csr_y;

    switch(c)
    {
        case 0x08://backspace
             if(x !=0) x--;
             break;
        case 0x09://TAB
             x = (x+8) % VGA_MAXX;
             break;
        case '\r'://carriage return
             x = 0;
             break;
        case '\n'://BS
             x = 0;
             y = y+1;
             break;
        default: 
             if(c >= ' ')
             {
               where = s_scrn.textmemptr + y*80+x;
               *where = c|s_scrn.attrib<<8;
               x++;
             }
    }/*end of switch*/

    if(x>80)
    {
      x = 0;
      y ++;
    }     

   move_csr(x,y);
   scroll(); 
}
void puts(const s8int* str)
{
   u32int len = strlen((u8int*)str);
   s32int i;
   for(i = 0;i < len;i++)
       putch(str[i]);
}

void puts_hex(u32int n)
{
   int i;
   s8int r;
   puts("0x");
   for(i=28;i>=0;i-=4)
   {
     r = (n >> i)&0xF;
     if(r>=0xA)
     {
         putch(r-0xA+'A');
     }else
     {
         putch(r+'0');
     }
   }
}

void puts_dec(s32int n)
{
   char c[32];
   int i,j;

   for(i=0;i<32;i++)
   {
      c[i] = n%10+'0';
      n /= 10;
      if (n == 0)
          break;
   }
   c[i+1]=0;
   for(j=0;j<i;j++,i--)
   {
      char tmp;
      tmp = c[i];
      c[i] = c[j];
      c[j] = tmp;
   }
   puts(c);
};

void settextcolor(u8int forecolor,u8int backcolor)
{
   s_scrn.attrib = forecolor | backcolor << 4;
}
void init_video()
{
  s_scrn.textmemptr = (u16int *)0xB8000;
  s_scrn.attrib = 0x0F;
  s_scrn.csr_x = 0;
  s_scrn.csr_y = 0;
  settextcolor(0xF,0x1);
  cls(); 
}


